package com.nightpiter.view.graphics;

import static java.lang.Math.pow;
import static java.lang.Math.sqrt;

import com.nightpiter.model.objects.Coordinated;
import com.nightpiter.model.objects.Coordinates;
import com.nightpiter.view.Calculator.Mode;

public class PointF {

	public float x;

	public float y;

	public PointF() {
		set();
	}

	public PointF(PointF other) {
		set(other);
	}

	public PointF(float x, float y) {
		set(x, y);
	}

	public PointF(Coordinates coordinates) {
		set(coordinates);
	}

	public PointF(Coordinated coordinated, Mode mode) {
		set(coordinated, mode);
	}

	public void set() {
		this.x = 0;
		this.y = 0;
	}

	public void set(PointF other) {
		this.x = other.x;
		this.y = other.y;
	}

	public void set(float x, float y) {
		this.x = x;
		this.y = y;
	}

	public void set(Coordinates coordinates) {
		this.x = coordinates.x;
		this.y = coordinates.y;
	}

	public void set(Coordinated coordinated, Mode mode) {
		if (mode == Mode.LOCATION) {
			this.set(coordinated.getLocation());
		} else {
			this.set(coordinated.getPosition());
		}
	}

	public void scale(float scale) {
		this.x *= scale;
		this.y *= scale;
	}

	public void add(PointF other) {
		this.x += other.x;
		this.y += other.y;
	}

	public void subtract(PointF other) {
		this.x -= other.x;
		this.y -= other.y;
	}

	public void normalize() {
		float length = (float) sqrt(pow(this.x, 2) + pow(this.y, 2));
		if (length != 0) {
			this.x /= length;
			this.y /= length;
		}
	}

	public void rotateCW() {
		float temp = x;
		x = y;
		y = -temp;
	}

	public float distanceTo(PointF other) {
		return (float) sqrt(pow(this.x - other.x, 2) + pow(this.y - other.y, 2));
	}

	public float distanceTo(Point other) {
		return (float) sqrt(pow(this.x - other.x, 2) + pow(this.y - other.y, 2));
	}

	public static float distance(PointF first, PointF second) {
		return (float) sqrt(pow(first.x - second.x, 2)
				+ pow(first.y - second.y, 2));
	}

	public static float distance(PointF first, Point second) {
		return (float) sqrt(pow(first.x - second.x, 2)
				+ pow(first.y - second.y, 2));
	}

	public static PointF difference(PointF first, PointF second) {
		return new PointF(first.x - second.x, first.y - second.y);
	}

	public static PointF sum(PointF first, PointF second) {
		return new PointF(first.x + second.x, first.y + second.y);
	}

	public static PointF averaged(PointF first, PointF second) {
		return new PointF((first.x + second.x) / (float) 2,
				(first.y + second.y) / (float) 2);
	}

	public static PointF averaged(PointF first, PointF second, int firstWeight,
			int secondWeight) {
		return new PointF((first.x * firstWeight + second.x * secondWeight)
				/ (float) (firstWeight + secondWeight),
				(first.y * firstWeight + second.y * secondWeight)
						/ (float) (firstWeight + secondWeight));
	}

	public static PointF averaged(PointF first, PointF second,
			float firstWeight, float secondWeight) {
		return new PointF((first.x * firstWeight + second.x * secondWeight)
				/ (firstWeight + secondWeight),
				(first.y * firstWeight + second.y * secondWeight)
						/ (firstWeight + secondWeight));
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof PointF) {
			PointF other = (PointF) o;
			return (this.x == other.x && this.y == other.y);
		} else {
			return false;
		}
	}

	public String toString() {
		return "(" + x + ";" + y + ")";
	}

}
